Release 1.1.3 is a maintenance release, bringing a kernel upgrade, to address the kernel vulnerability CVE-2022-0847, know as dirty pipe.
IOhubOS is a Linux-based distro designed for Industrial and IIoT environments, ready to run Docker-based applications.
Its main usages are:
- data collection
- charting
- applications orchestration
- integrating field devices (PLCs, IoT, and Industrial sensors, etc.), cloud services (e.g., AWS Timestream, Azure IoT, etc.), on-premise systems/databases (e.g., InfluxDB, Grafana, MES, ERP, etc.)
Its main characteristics are:
- It is a live distro, designed to be resilient to frequent power outages, with read-only filesystems.
- It can be used offline, with no internet connection.
- It provides firmware upgrades and downgrades capabilities with no impact on installed applications.
- It can be used on edge devices, inside a control panel, or as an industrial router.
- When used as a router, it can fully isolate all the connected devices from the internet and provide a secure, isolated network.
- It provides port forwards to the connected devices when used as a router.
- It provides routes definition to other networks.
- It does not require any complicated configuration or system administration skills; the whole configuration is centralized in a single file.
- It provides a complete Docker-based runtime environment, with a full set of tools to deploy, run and manage applications.
- It can be extended at the firmware level or during runtime without affecting the underlying operating system.
- It provides out-of-the-box WiFi client mode when an ethernet connection is not available.
- When configured in router mode, it provides an out-of-the-box WiFi access point mode for edge devices/sensors.
- It provides SSH access through password or SSH keys.
- It provides an internal Docker registry to store and share images for fast and disconnected operations.
- It provides Docker deployment capability just copying an application to the deployment folder.
- It provides firmware upgrade/downgrade capability, just copying the firmware to the deployment folder.
- It provides an administration API to manage the Docker applications deployments.
- It self configures a WireGuard VPN client.
- It self configures a Zerotier VPN client.
IOhubOS is the Open Source evolution of the proprietary IOhub technology developed by EZ VPN.
IOhubOS is backward compatible with the existing IOhub; existing IOhub application can be exported and deployed on IOhubOS.
While the existing IOhub technology is proprietary, it is still used in many industries and is used in a wide range of environments.
The new IOhubOS aims to become the de-facto standard operating system for Industrial and IIoT environments.
IOhubOS will eventually replace the existing IOhub installations, and the IOhubOS will be the new standard operating system for Industrial and IIoT environments.
All the Docker images created for IOhub, can be used, at no cost, in IOhubOS.
- x86_64 architecture (ARM compatibility will follow).
- 1GbByte of RAM.
- 16GByte of storage.
- One or two network adapters.
- Download the installer image from here
- Flash
installer.img
to a USB stick using any available tool, e.g.,Rufus
on Windows,balenaEtcher
on Windows, and macOS. - Boot from the USB stick.
- Run
iohub-installer <destination disk device> [<first network adapter>]
If you do not know the disk device, you can run the lsblk
command to get a list of available disks. It will probably be something like /dev/sda
or /dev/mmcblk0
.
If you do not know the name of your network device, the installer will run an autodetect procedure using the first network adapter found with a cable connected to a network with a DHCP server. You can otherwise run the lshw -class network -short
command to see a list of the available network interfaces
The installer will ask you for the root password to use later to configure the system.
Once IOhubOS is installed, it will ask you to press enter to shut down the system. After the system has shut down, you can remove the USB stick and boot it up again.
Once the system is started, after a few seconds, you will see on the console a message with the name of the network interface used to connect to the network and its IP address.
Note: the first boot may take a while, because the whole system is set up first the first time.
To configure the system, you can either log on to the console as root or use an SSH client, using the password you provided during the installation. The SSH server is by default enabled after the first boot, allowing you to connect to the system using SSH. You can disable it later.
You can configure almost every IOhubOS behavior just by editing the /iohub/envvars
file.
You can change the configuration using one of the available editors installed, vi
and nano
.
Once you change the configuration, you must reboot the system to apply the changes.
You can enable/disable the SSH server by setting the IOHUBOS_OPENSSH_ENABLED
variable to true/false
.
If you want to access the system using an SSH key, set the public key in the IOHUBOS_SSH_PUBLIC_KEY
variable.
You can configure the IOhubOS networking in two ways:
standalone mode
router mode
The variable IOHUBOS_NETWORK_MODE
can be set to standalone
or router
.
Only one network interface is used, identified in the configuration as ETH0 (ETH0 is not the real device name, it is meant as an identifier for the main interface).
The network interface can be configured in DHCP or static mode, configuring the variables below:
IOHUBOS_ETH0_MODE='dhcp' # dhcp/static
IOHUBOS_ETH0_IP='' # e.g. 192.168.190.254
IOHUBOS_ETH0_NETMASK='' # e.g. 255.255.255.0
IOHUBOS_ETH0_GATEWAY='' # e.g. 192.168.190.1
IOHUBOS_ETH0_DNS='' # space separated list, e.g. 192.168.190.1 8.8.8.8
Two interfaces are used, identified in the configuration as ETH0 and ETH1 (ETH0/ETH1 are not the real device names, they are meant as identifiers for the main and secondary interface).
ETH0 is used as the main interface, connected to the local LAN, and ETH1 is used as the secondary interface, where the devices/sensors are connected.
ETH0 can be configured as in the standalone mode. ETH1 can be configured only with a static IP address, configuring the variables below:
IOHUBOS_ETH1_DEVICE='' # e.g. enp1s0
IOHUBOS_ETH1_IP='' # e.g. 10.11.12.13
IOHUBOS_ETH1_NETMASK='' # e.g. 255.255.255.0
If you do now know the name of the ETH1 network device, you can run the lshw -class network -short
command to get a list of available network devices.
When router mode is configured, you can enable a DHCP server for the ETH1 network. The DHCP server can be configured using the variables below:
IOHUBOS_DHCP_SERVER_ENABLED='false' # dhcp server on eth1
IOHUBOS_DHCP_SERVER_FROM='' # e.g. 10.11.12.100
IOHUBOS_DHCP_SERVER_TO='' # e.g. 10.11.12.199
IOHUBOS_DHCP_SERVER_DNS='' # comma separated list, e.g. 192.168.190.1, 8.8.8.8
If you have available a WiFi interface, you can enable WiFi client mode. When enabled, the system will try to connect to the WiFi network, using the SSID and WPA password provided in the configuration (only WPA/WPA2 connections are compatible).
When the Wifi client mode is enabled, the cabled main interface is disabled. Any feature configured for ETH0 will be used applied to the WiFi interface.
You can enable Wifi client mode by setting the IOHUBOS_WIFI_MODE
variable to client
and configuring the WPA SSID and password in the IOHUBOS_WIFI_CLIENT_SSID
and IOHUBOS_WIFI_CLIENT_PASS
variables.
IOHUBOS_WIFI_MODE='client'
IOHUBOS_WIFI_DEVICE='' # wifi interface. 'auto' for autodiscovery
IOHUBOS_WIFI_CLIENT_SSID='' # wifi client ssid
IOHUBOS_WIFI_CLIENT_PASS='' # wifi client password
If you do not know the name of the WiFi network device, you can run lshw -class network -short
to get a list of available network devices or use auto
to autodetect the WiFi interface (if you have multiple WiFi interfaces, no detection ordering is guaranteed).
If you have available a WiFi interface, you can enable WiFi Access Point mode. The AP mode is available only in router
mode. The AP is bound to the ETH1 network interface.
Usually, you want to have a DHCP server available for the devices connecting to the AP.
You can enable the WiFi AP mode by setting the IOHUBOS_WIFI_MODE
variable to ap
and configuring the WPA SSID and password in the IOHUBOS_WIFI_AP_SSID
and IOHUBOS_WIFI_AP_PASS
variables.
IOHUBOS_WIFI_MODE='ap'
IOHUBOS_WIFI_DEVICE='' # wifi interface. 'auto' for autodiscovery
IOHUBOS_WIFI_AP_SSID='' # wifi ap ssid
IOHUBOS_WIFI_AP_PASS='' # wifi ap password
Suppose you do not know the name of the WiFi network device. In that case, you can run lshw -class network -short
to get a list of available network devices or use auto
to autodetect the WiFi interface (if you have multiple WiFi interfaces, no detection ordering is guaranteed).
Setting the variable IOHUBOS_FIREWALL_ROUTER_TO_INTERNET
to false
, the devices connected to the ETH1 network will not have any access to the LAN on ETH0 and therefore to the internet. You might want to use this mode if you have industrial devices to keep safe from the internet.
Setting the variable IOHUBOS_FIREWALL_ROUTER_TO_INTERNET
to true
, the devices connected to the ETH1 will have standard access to the LAN on ETH0 and therefore to the internet.
You can change the timezone of your IOhubOS instance by changing the value of the IOHUBOS_TIMEZONE
variable, using a value from the tz database.
You can upgrade/downgrade the running firmware of your IOhubOS instance by copying a firmware.tgz
file to the /iohub/firmware
directory of your IOhubOS instance and rebooting the system.
You can disable the auto-upgrade/downgrade capability by setting the IOHUBOS_UPGRADER_ENABLED
variable to false
.
By setting the variable IOHUBOS_DOCKER_ENABLED
to true
, all the Docker functionalities described below are enabled. All the enabled user applications will be started upon boot.
You can deploy Docker applications running in your IOhubOS instance by copying the packaged application to the /iohub/deploy
directory of your IOhubOS instance and rebooting the system.
You can disable the auto-deploy capability by setting the IOHUBOS_DEPLOYER_ENABLED
variable to false
.
The format/content of the deployable package is described in the Docker application deployment documentation.
By setting IOHUBOS_DOCKER_REGISTRY_ENABLED
to true
, an internal Docker registry will run on the IOhubOS instance. You can use it to allow the device to keep working even when internet access is not available, have a faster startup of applications, and minimize network traffic
The Docker images embedded in the firmware are by default already available in the registry. To add new images to the registry, read the Docker registry section below.
You can expose the internal Docker registry on ETH0 or ETH1 by setting to true
the variables IOHUBOS_DOCKER_REGISTRY_EXPOSE_ETH0
and IOHUBOS_DOCKER_REGISTRY_EXPOSE_ETH1
.
You can change the default registry port (5000 by default) by setting the IOHUBOS_DOCKER_REGISTRY_PORT
variable.
IOHUBOS_DOCKER_REGISTRY_PORT
has been introduced in version 1.1.2. In the previous versions it is not used.
You can enable an administration API. The Admin API allows you to manage the installed Docker applications, as fully described here
.
The Admin API is disabled by default. You need to set a strong password, in the variable IOHUBOS_ADMIN_API_AUTH_TOKEN
, for the Admin API access. If the password is not strong enough, the Admin API will be disabled, and any call will give you a message asking to set a stronger password.
The admin API will be available at the port defined in the variable IOHUBOS_ADMIN_API_SERVER_PORT
.
The full API in OpenAPI 3.0 format is documented here
.
IOHUBOS_ADMIN_API_ENABLED='false' # enable admin API
IOHUBOS_ADMIN_API_SERVER_PORT='9999' # http port
IOHUBOS_ADMIN_API_AUTH_TOKEN='' # header auth token
Please note that the Admin API gives full access to the existing Docker instances and can be used to manage the Docker instances. Turn it on only if needed.
When in router mode, you can define TCP port forwards in the /iohub/forwards-tcp
file.
Each line of the file, not starting with a #
, is a forward definition.
The format of the forward definition is:
SRC_PORT=DST_IP:DST_PORT
where:
SRC_PORT
is the exposed port on ETH0DST_IP
is the IP of the device to forward toDST_PORT
is the port on the device to forward to
If a forward definition collides with an exposed TCP port (SSH, Docker registry, ...), the forward will be ignored.
When in router mode, you can define UDP port forwards in the /iohub/forwards-udp
file.
Each line of the file, not starting with a #
, is a forward definition.
The format of the forward definition is:
SRC_PORT=DST_IP:DST_PORT
where:
SRC_PORT
is the exposed port on ETH0DST_IP
is the IP of the device to forward toDST_PORT
is the port on the device to forward to
You can define routes to other networks modifying the /iohub/routes
file.
Each line of the file, not starting with a #
, is a route definition.
The format of the route definition is:
DESTINATION/NETMASK:GATEWAY
where:
DESTINATION/NETMASK
is the remote network to reach with CIDR (e.g. 192.168.152.0/24)GATEWAY
is the IP of the gateway to the remote network
IOhubOS provides auto-configuration to a WireGuard VPN server or to a Zerotier VPN server.
Feature | WireGuard | Zerotier |
---|---|---|
Open source | Yes | Yes |
In linux kernel | Yes | no |
Self hosted | Yes | No |
Cloud service | No | Yes |
Protocols | UDP | UDP |
Maturity | 4/5 | 2/5 |
Peer-to-peer | No | Yes |
Fine grained ACL | No | Yes |
Note: From version 1.1.1, the variables IOHUBOS_VPN_*
are deprecated. Please use IOHUBOS_WIREGUARD_*
instead.
WireGuard configuration can be found in the /iohub/envvars.d/1.1.1-envars
file. To enable the WireGuard VPN, you need to set the variable IOHUBOS_WIREGUARD_ENABLED
to true
.
IOHUBOS_WIREGUARD_ENABLED='false' # enable WireGuard vpn
IOHUBOS_WIREGUARD_SERVER_PUBLIC_KEY='' # WireGuard server public key
IOHUBOS_WIREGUARD_BOX_NUMBER='' # a number > 1; must be unique for each box and > 1 (1 is the server)
IOHUBOS_WIREGUARD_NETWORK='' # internal WireGuard vpn network, e.g. 100.90.56.0/24
IOHUBOS_WIREGUARD_SERVER_IP_ADDRESS='' # public server ip address
IOHUBOS_WIREGUARD_SERVER_IP_PORT='' # public server port, e.g. 51820
IOHUBOS_WIREGUARD_EXPOSE='auto' # 'auto' to expose automatically the WireGuard interface, otherwise set manually to set the AllowedIPs
IOHUBOS_WIREGUARD_ACCESS_HOST='false' # if 'true', access to the Docker applications through VPN is granted. Denied otherwise.
TODO
Starting from version 1.1.1, IOhubOS provides auto-configuration to Zerotier.
Zerotier configuration can be found in the /iohub/envvars.d/1.1.1-envars
file. To enable Zerotier, you need to set the variable IOHUBOS_ZEROTIER_ENABLED
to true
.
IOHUBOS_ZEROTIER_ENABLED='false' # enable Zerotier
IOHUBOS_ZEROTIER_NETWORK='' # Zerotier network id
IOHUBOS_ZEROTIER_ACCESS_HOST='false' # if 'true', access to the Docker applications on host ip host is granted.
TODO
You can add your own customizations to the distro creating the folder custom
at the top level of the repo and adding files in it.
During the OS installation, if the folder custom
exists, it's content will be copied in the /
directory of the IOhubOS distro.
Existing files with the same path will be overwritten.
The Docker registry is enabled by default. You can disable it by setting the variable IOHUBOS_DOCKER_REGISTRY_ENABLED
to false
.
You can add new images to the registry by:
- setting to
true
the variableIOHUBOS_DOCKER_REGISTRY_RESCAN
- copying a Docker image to the
/iohub/runtime/iohub-registry
directory of your IOhubOS instance and rebooting the system.
When IOHUBOS_DOCKER_REGISTRY_RESCAN
is true
, the folder /iohub/runtime/iohub-registry
will be scanned for new images and added to the registry.
if IOHUBOS_DOCKER_REGISTRY_RESCAN_DELETE
is 'true', the image file is deleted, once imported to the registry.
Below is the procedure to create the Docker images for the automatic upload to the registry.
docker pull <docker image name>
docker save <docker image name> | gzip > <somename>.tar.gz
For example. to import the image mysql:5.7.36 from Docker Hub into the internal registry, you can do:
docker pull mysql:5.7.36
docker save mysql | gzip > mysql.tar.gz
Once you have created the gzipped files containing the images, you can copy them to the /iohub/runtime/iohub-registry
directory of your IOhubOS instance and reboot the system.
Note: the name of the gzipped file is not relevant. However the extension must be .tar.gz
.
Upon reboot, the folder /iohub/docker/apps
is scanned for Docker execution.
Any folder below /iohub/docker/apps
represent a Docker application, whose name is the folder name. The folder name must be a valid Docker Compose application name; the format accepted is 1 to 64 characters long, starting with a lowercase letter, followed by any number of lowercase letters, numbers, hyphens, or underscores.
one file must be present in the folder /iohub/docker/apps/<app_name>
:
start.sh
: the script to run when the application is started
If start.sh
is present and has mode 755, the application will start upon boot.
Otherwise, the application will be ignored.
start.sh
#!/bin/sh
docker run -d --name=grafana -p 3000:3000 grafana/grafana
start.sh
#!/bin/sh
[ -d /iohub/docker/apps/<app name>/volumes/app-vol ] || mkdir -p /iohub/docker/apps/<app name>/volumes/app-vol
[ -d /iohub/docker/apps/<app name>/volumes/ezvpn-grafana-vol-3 ] || mkdir -p /iohub/docker/apps/<app name>/volumes/ezvpn-grafana-vol-3
[ -d /iohub/docker/apps/<app name>/volumes/ezvpn-influxdb-vol-1 ] || mkdir -p /iohub/docker/apps/<app name>/volumes/ezvpn-influxdb-vol-1
docker-compose -f /iohub/docker/apps/<app name>/docker-compose.yml up -d
docker-compose.yml
version: "3.8"
services:
ezvpn-grafana:
image: us-central1-docker.pkg.dev/ez-shared/iohub/iohub-grafana
environment:
INFLUXDB_HOST: "ezvpn-influxdb"
GF_LOG_MODE: "console"
GF_LOG_LEVEL: "error"
ports:
- 3000:3000
depends_on:
- ezvpn-influxdb
volumes:
- ezvpn-grafana-vol-3:/var/lib/grafana
networks:
- <app name>-net
ezvpn-influxdb:
image: us-central1-docker.pkg.dev/ez-shared/iohub/iohub-influxdb-v1
environment:
INFLUXDB_DATA_QUERY_LOG_ENABLED: "false"
INFLUXDB_DB: "data"
INFLUXDB_HTTP_LOG_ENABLED: "false"
INFLUXDB_RP: "180d"
INFLUXDB_REPORTING_DISABLED: "true"
expose:
- 8086
volumes:
- ezvpn-influxdb-vol-1:/var/lib/influxdb
networks:
- <app name>-net
ezvpn-mqtt:
image: us-central1-docker.pkg.dev/ez-shared/iohub/iohub-mqtt
restart: "no"
expose:
- 1883
networks:
- <app name>-net
ezvpn-mqtt-influxdb:
image: us-central1-docker.pkg.dev/ez-shared/iohub/iohub-mqtt-influxdb
restart: "no"
environment:
MQTT_HOST: "ezvpn-mqtt"
INFLUXDB_HOST: "ezvpn-influxdb"
depends_on:
- ezvpn-mqtt
- ezvpn-influxdb
networks:
- <app name>-net
volumes:
ezvpn-grafana-vol-3:
driver: local
driver_opts:
type: none
device: /iohub/docker/apps/<app name>/volumes/ezvpn-grafana-vol-3
o: bind
ezvpn-influxdb-vol-1:
driver: local
driver_opts:
type: none
device: /iohub/docker/apps/<app name>/volumes/ezvpn-influxdb-vol-1
o: bind
app-vol:
driver: local
driver_opts:
type: none
device: /iohub/docker/apps/<app name>/volumes/app-vol
o: bind
global-vol:
driver: local
driver_opts:
type: none
device: /iohub/docker/global/volumes/global-vol
o: bind
networks:
<app name>-net:
Note: when uploading a Docker Compose file through the Admin API, a start.sh
file is generated automatically.
You can package your Docker application definition in a zip file and upload it to the /iohub/deploy
folder to have it deployed on the next reboot.
The structure of the zip file is described below:
docker
|--> apps
| |--> <app 1 name>
| | |--> docker-compose.yml
| | |--> start.sh
| |--> <app 2 name>
| | |--> docker-compose.yml
| | |--> start.sh
| |--> <app 3 name>
| | |--> docker-compose.yml
| | |--> start.sh
A GUI composer application is in the roadmap. Meanwhile, if you do not want to create a zipped file manually, you can use the EZ VPN management site for free to create a zipped file.
You create a Development IOhub instance, design your applications and download the production zip file. You can save the downloaded file in the /iohub/deploy
folder with no modification.
The applications created with EZ VPN IOhub are compatible with the IOhubOS. If an IOhub application is using the global MQTT broker, the following variables are available:
IOHUBOS_GLOBAL_MQTT='true'
IOHUBOS_GLOBAL_MQTT_IMG="${IOHUBOS_HOSTNAME}:${IOHUBOS_DOCKER_REGISTRY_PORT}/iohubos/iohubos-mqtt"
IOHUBOS_GLOBAL_MQTT_NAME="ezvpn-global-mqtt"
IOHUBOS_GLOBAL_MQTT_NET="ezvpn-global-mqtt-net"
If IOHUBOS_GLOBAL_MQTT
is true
, a global MQTT broker is started at boot. The default values of the remaining variables are compatible with the old IOhub applications.
If you are not using IOhub, you can change those values at your convenience, without using the ezvpn
prefix.
IOhubOS is based on a SquashFS read-only file system.
However, it is designed to be customized by the user.
Upon each reboot, the content of the /iohub/live
folder is copied over /
in a volatile overlay file system, mounted over the SquashFS read-only file system. You can therefore override or extend functionalities implemented in the base distro, even if the base distro in written in a read-only file system.
Note: the overlay file system is hosted in RAM. Do not copy huge files to the /iohub/live
folder because they will be copied to the RAM.
The IOhubOS firmware does not include any default configuration. The network is disabled; no firewall is configured; no default route is set; no DHCP server is available; no SSH server is running, no default DNS is set, etc.
Upon reboot, the service iohub-bootstrap.service
is started.
iohub-bootstrap
is the heart of the IOhubOS firmware. It defines the lifecycle of all the services defined above and of user/customizable services.
Below is defined the full lifecycle of the IOhubOS firmware, as defined by the iohub-bootstrap
service (see the section File System Structure for a deeper understanding of the IOhubOS structure).
- the writable partition is mounted on
/iohub
/iohub/runtime/iohub-bootstrap/postmount
is executed/iohub/runtime/iohub-bootstrap/presetup
is executed- if
/iohub/setup.done
is missing, the/iohub
folder is initialized creating the needed folders and files and/iohub/setup.done
is created /iohub/runtime/iohub-bootstrap/postsetup
is executed- if
/iohub/ask.noboot
is not present:/iohub/runtime/iohub-bootstrap/prelivesync
is executed- if
/iohub/disable.livesync
is not present:- copy
/iohub/live/
over/
- copy
/iohub/runtime/iohub-bootstrap/postlivesync
is executed/iohub/runtime/iohub-bootstrap/preliveactions
is executed- if
/iohub/disable.actions
is not present:- for each file in
/usr/bin/iohub-actions.d
:- if the file is executable, execute it as sub command
- if the file is not executable, execute its content
- for each file in
/iohub/runtime/iohub-bootstrap/postliveactions
is executed
/iohub/runtime/iohub-bootstrap/end
is executed
Each service is implemented by one or more scripts in the /usr/bin/iohub-actions.d
folder.
You can disable some of the services by setting to false a specific variable.
For example, you can override the predefined networking definition setting to false
the variable IOHUBOS_NETWORK_CONFIG
.
You can then create your custom network configuration creating a file named like /iohub/live/usr/bin/iohub-actions.d/0200-my-custom-network.sh
containing your custom network configuration.
Upon reboot, your script 0200-my-custom-network.sh
will be temporarily saved in the /usr/bin/iohub-actions.d
folder and executed by the iohub-bootstrap
service.
Please note that the script's name defines the execution order with respect to the other scripts in the /usr/bin/iohub-actions.d
folder.
By creating custom actions, you can extend the behavior of IOhubOS as you like, applying temporary modifications to the read-only file system.
At every reboot, the actions will be re-played on the SquashFS file system.
The postmount
, presetup
, etc. scripts are hooks that can customize the service behavior, implement even more dynamic actions, and potentially alter the lifecycle.
You might dynamically alter variable values, changing the behavior of the scripts in /usr/bin/iohub-actions.d
.
During the installation, the destination disk device is partitioned in the following way:
- partition 1: contains the GRUB bootloader
- partition 2: contains the IOhubOS read-only file system
- partition 3: contains the IOhubOS read-only file system
- partition 4: contains a writable partition, mapped on
/iohub
After the initial installation, the GRUB bootloader points to the second partition as the default boot device.
When a new firmware is installed, it gets installed in the third partition. Upon successful installation, the GRUB bootloader is then updated to point to the third partition, and the system is rebooted.
In such a way, using the GRUB boot menu, you can boot from the previous firmware, still present in the second partition.
When a new firmware is installed, the GRUB bootloader is updated again to point to the second partition, in a round robin fashion.
Using this technique, you can boot from the previous firmware or the new firmware and run upgrades/downgrades when needed.
The fourth partition is the writable partition. It is used to store any user data, or custom configuration/behavior:
- to override the default behavior of IOhubOS
- to store the Docker Applications and their volumes/databases
- to store the IOhubOS configuration, used both by partitions 2 and 3
- to store the Docker registry
- etc.
/--> # read only file system
|--> iohub/ # writable partition
| |--> deploy/ # folder for automatic apps deployment
| |--> docker/ # folder for Docker Applications
| | |--> apps/ # user applications
| | | |--> <app 1>
| | | |--> <app 2>
| | | |--> <app 3>
| | |--> global/ # global applications
| | |--> registry/ # internal Docker registry
| |--> envvars/ # user environment variables
| |--> envvars.d/ # user environment variables - firmware version specific
| | | |--> 1.0.0-envvars # <empty>
| | | |--> 1.0.2-envvars # <empty>
| | | |--> 1.0.3-envvars # <empty>
| | | |--> 1.1.0-envvars # vpn configuration
| | | |--> 1.1.1-envvars # WireGuard and Zerotier configuration
| |--> firmware/ # folder for automatic firmware deployment
| |--> forwards-tcp # tcp forwards definitions
| |--> forwards-udp # udp forwards definitions
| |--> live/ # folder for live configuration. copied over / at boot
| |--> routes # routes definitions
| |--> runtime/ # folder for permanent data used by scripts/apps
| | |--> iohub-bootstrap/ # hooks definitions for iohub-boostrap
| | |--> iohub-registry/ # folder for Docker registry automatic import
| | |--> wireguard/ # folder for WireGuard keys
| | |--> zerotier/ # folder for Zerotier configuration
| |--> sysvars # system environment variables
|--> usr/
| |--> bin/
| | |--> iohub-actions.d/ # folder for iohub-bootstrap scripts (read only)
| |--> lib/
| | |--> iohub/
| | | |--> envvars.d/ # folder for specific version default configuration (read only)
iohub-install-firmware
: it can be used to install a new firmware manually on the next partition (partition 3 when partition 2 is the default, partition 2 otherwise).iohub-next-partition
: it returns the partition number, not in use (1 or 2, for partitions 2 and 3).iohub-set-boot-default
: Set the default boot partition. Optionally change the entry menu description.
As an example of how it is possible to modify the IOhubOS behavior, we will adjust the default Docker logging behavior, enabling logging to GCP.
Based on the Docker instructions to implement the logging to GCP here,
we create three files below the /iohub/live
folder to have them copied over their correct location upon boot.
/iohub/live/etc/docker/daemon.json
: the Docker logging configuration file./iohub/live/etc/docker/googlecloud-serviceaccount.json
: the GCP credentials file./iohub/live/etc/systemd/system/diocker.service.d/gcplogging.conf
: the environment variable definition, to provide Docker the GCP credentials.
daemon.json
{
"log-driver": "gcplogs",
"log-opts": {
"gcp-project": "<your GCP project>",
"mode": "non-blocking",
"max-buffer-size": "50m"
}
}
googlecloud-serviceaccount.json (generated on GCP, data hidden here)
{
"type": "service_account",
"project_id": "<your GCP project>",
"private_key_id": "<...>",
"private_key": "-----BEGIN PRIVATE KEY-----\n<...>\n-----END PRIVATE KEY-----\n",
"client_email": "<...>",
"client_id": "<...>",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/<...>"
}
gcplogging.conf
[Service]
Environment="GOOGLE_APPLICATION_CREDENTIALS=/etc/docker/googlecloud-serviceaccount.json"
Reboot the system to apply the changes. Your Docker engine should now be logging to GCP.
IOhubOS is distributed under the terms of The GNU Affero General Public License v3.0.
See LICENSE for details.
SPDX-License-Identifier: AGPL-3.0-only
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.